import java.io.IOException;
import java.io.Serializable;

import jdbm.PrimaryStoreMap;
import jdbm.RecordManager;
import jdbm.RecordManagerFactory;
import jdbm.SecondaryKeyExtractor;
import jdbm.SecondaryTreeMap;


/**
 * More advanced example to demonstrate Map usage.
 * 
 * @author Jan Kotek
 *
 */
public class HelloWorld2 {

	static class Person implements Serializable{
		
		/** never forget this, very important for serialization*/
		private static final long serialVersionUID = -3321252970661193623L;
		final String name;		
		final String town;
		final String country;
		
		/** some data to object class bigger */
		final byte[] balast = new byte[1024];

		public Person(String name, String town, String country) {
			this.name = name;
			this.town = town;
			this.country = country;			
		}

		@Override
		public String toString() {
			return "Person [name=" + name + ", town=" + town + ", country=" + country + "]";
		}
				
		/** snip getters and setters*/
		
	}
	

	
	public static void main(String[] args) throws IOException {
		RecordManager recman = RecordManagerFactory.
				createRecordManager("HelloWorld2");
		/**
		 * Create primary map which is used to store records.  
		 * Data can be also stored in PrimaryTreeMap and PrimaryHashMap,
		 * but this is more efficient for large objects. 
		 */
		PrimaryStoreMap<Long,Person> main = recman.storeMap("recman");
		
		/**
		 * Create secondary index which points to Person name.
		 * SecondaryMap is readonly, it is updated by PrimaryMap.
		 *  
		 * Secondary map have three types, 
		 * first is type of secondary index (string),
		 * second and third are copied from primary map.
		 */
		SecondaryTreeMap<String, Long, Person> nameIndex = main.secondaryTreeMap("nameIndex",
						new SecondaryKeyExtractor<String, Long, Person>() {
							public String extractSecondaryKey(Long key, Person value) {
								return value.name;
							}					
						});
		
		/**
		 * Another secondary map which points to town and country
		 */
		SecondaryTreeMap<String, Long, Person> townIndex = main.secondaryTreeMap("townIndex",
				new SecondaryKeyExtractor<String, Long, Person>() {
					public String extractSecondaryKey(Long key, Person value) {
						/**
						 * Note format of map key
						 */
						return value.country+"/"+value.town;
					}					
				});
		
		/**
		 * And very simple index of Evil family members
		 */
		SecondaryTreeMap<Boolean, Long, Person> evilIndex = main.secondaryTreeMap("evilIndex",
				new SecondaryKeyExtractor<Boolean, Long, Person>() {
					public Boolean extractSecondaryKey(Long key, Person value) {
						return value.name.contains("Evil");
					}					
				});
		
		/**
		 * Clean up, if this example was run more times.
		 * All secondary indexes are updated automatically. 
		 */
		main.clear();
		
		
		/** 
		 * Add some data. 
		 * StoreMap does not have usuall 'put' method.
		 * Key is generated by Store, so use 'putValue' instead 
		 */
		main.putValue(new Person("James Bond","London","UK"));
		main.putValue(new Person("Austin Powers","London","UK"));
		main.putValue(new Person("Dr Evil","Vulcano Island","Ocean"));
		main.putValue(new Person("Scott Evil","Vulcano Island","Ocean"));		
		main.putValue(new Person("Vanessa Kensington","London","UK"));
		main.putValue(new Person("Alotta Fagina","Las Vegas","USA"));
				
		/**
		 * Persists inserted values
		 */
		recman.commit();
		
		/**
		 * Get persons with name Austin Powers
		 */
		System.out.println();
		System.out.println("Austin Powers: ");
		for(Person person:nameIndex.getPrimaryValues("Austin Powers")){
			System.out.println("  "+person);
		}
		
		/**
		 * Print all Persons who lives on Vulcano Island.
		 * First we must obtain key from primary map,
		 * then 
		 */
		System.out.println();
		System.out.println("Persons on Vulcano Island: ");
		for(Person person:townIndex.getPrimaryValues("Ocean/Vulcano Island")){
			System.out.println("  "+person);
		}
		

		/**
		 * Get everyone who is Evil
		 */
		System.out.println();
		System.out.println("Evil family: ");
		for(Person person:evilIndex.getPrimaryValues(true)){
			System.out.println("  "+person);
		}		
		
		recman.close();
	}
}

